
function uuid(){
    var s = [];
    var hexDigits = "0123456789abcdef";
    for (var i = 0; i < 36; i++) {
        s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
    }
    s[14] = "4";
    s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
    s[8] = s[13] = s[18] = s[23] = "-";
    var uuid = s.join("");
    return uuid;
}

var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var base64DecodeChars = new Array(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
/**
 * base64编码
 * 编码：base64encode(utf16to8(value));
 * 解码：utf8to16(base64decode(value));
 * @param {Object} str
 */
function base64encode(str){
    var out, i, len;
    var c1, c2, c3;
    len = str.length;
    i = 0;
    out = "";
    while (i < len) {
        c1 = str.charCodeAt(i++) & 0xff;
        if (i == len) {
            out += base64EncodeChars.charAt(c1 >> 2);
            out += base64EncodeChars.charAt((c1 & 0x3) << 4);
            out += "==";
            break;
        }
        c2 = str.charCodeAt(i++);
        if (i == len) {
            out += base64EncodeChars.charAt(c1 >> 2);
            out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
            out += base64EncodeChars.charAt((c2 & 0xF) << 2);
            out += "=";
            break;
        }
        c3 = str.charCodeAt(i++);
        out += base64EncodeChars.charAt(c1 >> 2);
        out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
        out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
        out += base64EncodeChars.charAt(c3 & 0x3F);
    }
    return out;
}
/**
 * base64解码
 * @param {Object} str
 */
function base64decode(str){
    var c1, c2, c3, c4;
    var i, len, out;
    len = str.length;
    i = 0;
    out = "";
    while (i < len) {
        /* c1 */
        do {
            c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
        }
        while (i < len && c1 == -1);
        if (c1 == -1)
            break;
        /* c2 */
        do {
            c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
        }
        while (i < len && c2 == -1);
        if (c2 == -1)
            break;
        out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
        /* c3 */
        do {
            c3 = str.charCodeAt(i++) & 0xff;
            if (c3 == 61)
                return out;
            c3 = base64DecodeChars[c3];
        }
        while (i < len && c3 == -1);
        if (c3 == -1)
            break;
        out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
        /* c4 */
        do {
            c4 = str.charCodeAt(i++) & 0xff;
            if (c4 == 61)
                return out;
            c4 = base64DecodeChars[c4];
        }
        while (i < len && c4 == -1);
        if (c4 == -1)
            break;
        out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
    }
    return out;
}
/**
 * utf16转utf8
 * @param {Object} str
 */
function utf16to8(str){
    var out, i, len, c;
    out = "";
    len = str.length;
    for (i = 0; i < len; i++) {
        c = str.charCodeAt(i);
        if ((c >= 0x0001) && (c <= 0x007F)) {
            out += str.charAt(i);
        }
        else
        if (c > 0x07FF) {
            out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
            out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
            out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
        }
        else {
            out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
            out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
        }
    }
    return out;
}
/**
 * utf8转utf16
 * @param {Object} str
 */
function utf8to16(str){
    var out, i, len, c;
    var char2, char3;
    out = "";
    len = str.length;
    i = 0;
    while (i < len) {
        c = str.charCodeAt(i++);
        switch (c >> 4) {
            case 0:
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
            case 7:
                // 0xxxxxxx
                out += str.charAt(i - 1);
                break;
            case 12:
            case 13:
                // 110x xxxx 10xx xxxx
                char2 = str.charCodeAt(i++);
                out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
                break;
            case 14:
                // 1110 xxxx10xx xxxx10xx xxxx
                char2 = str.charCodeAt(i++);
                char3 = str.charCodeAt(i++);
                out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
                break;
        }
    }
    return out;
}


/**
 * f4组件，提供对象的选择功能
 * Created by lifetime on 2015/9/9.
 */
function equals(src,obj)
{
	if (src == obj) {
		return true;
	}
	if (typeof(obj) == "undefined" || obj == null || typeof(obj) != "object") {
		return false;
	}
	var length = 0;
	var length1 = 0;
	for (var ele in src) length++;
	for (var ele in obj) length1++;
	if (length != length1) {
		return false;
	}
	if (obj.constructor == src.constructor) {
		for (var ele in this) {
			if (typeof(src[ele]) == "object") {
				if (!equals(src[ele],obj[ele]))return false;
			}
			else if (typeof(src[ele]) == "function") {
				if (!equals(src[ele].toString(),obj[ele].toString())) return false;
			}
			else if (src[ele] != obj[ele]) return false;
		}
		return true;
	}
	return false;
};

(function($){
	var f4DialogHtml = "PGRpdiBjbGFzcz0ibW9kYWwgZmFkZSIgaWQ9ImY0TW9kYWwiIHRhYmluZGV4PSItMSIgcm9sZT0iZGlhbG9nIgogICAgICAgICAgICAgYXJpYS1sYWJlbGxlZGJ5PSJmNE1vZGFsTGFiZWwiIGFyaWEtaGlkZGVuPSJ0cnVlIj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZGlhbG9nIj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWNvbnRlbnQiPgogICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWhlYWRlciI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iY2xvc2UiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS1kaXNtaXNzPSJtb2RhbCIgYXJpYS1oaWRkZW49InRydWUiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgJnRpbWVzOwogICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPGg0IGNsYXNzPSJtb2RhbC10aXRsZSIgaWQ9ImY0TW9kYWxMYWJlbCI+CiAgICAgICAgICAgICAgICAgICAgICAgIAnpgInmi6nmlbDmja4KICAgICAgICAgICAgICAgICAgICAgICAgPC9oND4KICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICA8ZGl2IGlkPSJmNFRhYmxlRGl2IiBjbGFzcz0ibW9kYWwtYm9keSI+CgogICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWZvb3RlciI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1kZWZhdWx0IiBkYXRhLWRpc21pc3M9Im1vZGFsIj7lhbPpl608L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGlkPSJmNE9rQnV0dG9uIiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5Ij7noa7lrpo8L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4=";
	if($('#f4Modal').length == 0){
		$('body').append(utf8to16(base64decode(f4DialogHtml)));
	}
	var searchHtml = '<div class="row" style="padding: 0px 10px 10px 10px;"><div class="input-group col-md-5 pull-right">';
	searchHtml += '<input type="text" class="form-control searchInput">';
	searchHtml += '<span class="input-group-btn">';
	searchHtml += '<button class="btn btn-default searchBtn" type="button">搜索</button>';
	searchHtml += '</span>';
	searchHtml += '</div></div>';
    var htmlTemplate = "<div class='input-group f4Contain'>";
    htmlTemplate += "<input type='text' class='form-control' style='background-color:white;' readonly value=''>";
    htmlTemplate += "<span class='input-group-addon f4Color' style='cursor:pointer;border-left: none;background-color: white;padding: 5px 8px;' ><i class='iconfont icon-chaxun' style='font-size: 20px;color: #FF008B;'></i></span>";
    htmlTemplate += "<input type='hidden' class='f4-inited' id='' name='' value='' />";
    htmlTemplate += "</div>";
    $.fn.f4 = function(){
        if($(this).hasClass("f4-inited")){
            var contain = $(this).closest(".f4Contain");

            return {
                getDisplayFormat : function(){
                    return $(contain.children("input")[0]).attr("displayFormat");
                },
                getCommitFormat : function(){
                    return $(contain.children("input")[0]).attr("commitFormat") || "id";
                },
                setEditable : function(isEdit){
                    contain.attr("isEditable",(isEdit||true) ? "true" : "false");
                    if(isEdit == "false"){
                        contain.children("input:first").removeClass("bg-white");
                    }else{
                        contain.children("input:first").addClass("bg-white");
                    }
                },
                setValue : function(obj){
                    var changedListener = contain.data("DataChangedListener");
                    if(obj){
                        var dis = this.getDisplayFormat();
                        var com = this.getCommitFormat();
                        var comps = contain.children("input");
                        var oldVal = $(comps[1]).attr("objValue");
                        var newVal = JSON.stringify(obj);
                        var isChange = (oldVal != newVal) || (oldVal != undefined && equals(oldVal,newVal));
                        if(isChange && changedListener){
                            var result = changedListener.call(this,oldVal,newVal);
                            if(result == undefined || result){
                                $(comps[0]).val(obj[dis]);
                                if(com == "_objValue_"){
                                    $(comps[1]).val(newVal);
                                }else{
                                    $(comps[1]).val(obj[com]);
                                }
                                $(comps[1]).attr("objValue",newVal);
                            }
                        }else{
                            $(comps[0]).val(obj[dis]);
                            if(com == "_objValue_"){
                                $(comps[1]).val(newVal);
                            }else{
                                $(comps[1]).val(obj[com]);
                            }
                            $(comps[1]).attr("objValue",newVal);
                        }
                    }else{
                        var comps = contain.children("input");
                        var oldVal = $(comps[1]).attr("objValue");
                        var newVal = obj;
                        var isChange = (oldVal != newVal) || (oldVal != undefined && equals(oldVal,newVal));
                        if(isChange && changedListener){
                            var result = changedListener.call(this,oldVal,newVal);
                            if(result == undefined || result){
                                $(comps[0]).val(newVal);
                                $(comps[1]).val(newVal);
                                $(comps[1]).attr("objValue",newVal);
                            }
                        }else{
                            $(comps[0]).val(newVal);
                            $(comps[1]).val(newVal);
                            $(comps[1]).attr("objValue",newVal);
                        }
                    }
                },
                getValue:function(){
                    try{
                        return JSON.parse($(contain.children("input")[1]).attr("objValue"));
                    }catch(e){
                        return null;
                    }
                },
                setChangedListener:function(listener){
                    contain.data("DataChangedListener",listener);
                }
            };
        }
        var html = $(htmlTemplate);
        var f4id = uuid();
        var str = $(this).attr("value");
        var displayFormat = $(this).attr("displayFormat") || "name";
        var commitFormat = $(this).attr("commitFormat") || "id";
        var isEdit = $(this).attr("isEditable") || "true";
        html.attr("isEditable",isEdit);
        var comps =html.children("input");
        if("false" == isEdit){
            $(comps[0]).removeClass("bg-white");
        }
        if(str){
            var obj = JSON.parse(str);
            $(comps[0]).val(obj[displayFormat]);
            if(commitFormat == "_objValue_"){
                $(comps[1]).val(str);
            }else{
                $(comps[1]).val(obj[commitFormat]);
            }
            $(comps[1]).attr("objValue",str);
        }
        $(comps[1]).attr("id",$(this).attr("id"));
        $(comps[1]).attr("name",$(this).attr("name"));
        if($(this).attr("name")){
        	$(comps[1]).addClass('form-field');
        }
        var inputAddon = $(html.children(".input-group-addon")[0]);
        inputAddon.attr("id",f4id);
        inputAddon.attr("url",$(this).attr("url"));
        inputAddon.attr("table",$(this).attr("table"));
        inputAddon.attr("urlParams",$(this).attr("urlParams"));
        $(comps[0]).attr("displayFormat",$(this).attr("displayFormat"));
        $(comps[0]).attr("commitFormat",$(this).attr("commitFormat"));
        
    	var refreshPagination = function(pinfo) {
    		var div = $('<div/>').css({
    			"position": "relative",
    		    "text-align": "right",
    		    "margin": "-20px 0"
    		});
    		var ul = $('<ul class="pager"></ur>');
    		if (pinfo && pinfo.pageIndexs) {
    			$(pinfo.pageIndexs).each(function(index, obj) {
    				var li = $('<li/>');
    				if (obj["class"]) {
    					li.addClass(obj["class"]);
    				}
    				li.append($('<a/>', {
    					"href" : "javascript:;"
    				}).text(obj.text));
    				ul.append(li);
    			});
    		}
    		$("#f4TableDiv").append(div.append(ul));
    	}
    	
    	$('#f4TableDiv').delegate(".pager>li","click",function(){
        	if($(this).hasClass('active') || $(this).hasClass('disabled')){
        		return false;
        	}
        	
        	var currentNum = $('#f4TableDiv .pager>li.active').text();
        	var pageNum = $(this).text();
        	if(pageNum == "«"){
        		pageNum = parseInt(currentNum) - 1; 
        	}else if(pageNum == "»"){
        		pageNum = parseInt(currentNum) + 1; 
        	}else{
        		pageNum = parseInt(pageNum);
        	}
        	var params = $("#f4TableDiv").attr('defaultParams')||'{}';
        	try {
        		params = JSON.parse(params);
			} catch (e) {
				params = {};
			}
			params.page = pageNum;
        	var buildUrl = $("#f4TableDiv").attr('defaultUrl')+"/" + encodeURI(JSON.stringify(params));
            $.getJSON(buildUrl,function(data){
                refreshTableData(data);
            });
        });
    	
    	$('#f4TableDiv').delegate(".searchBtn","click",function(){
    		var searchVal = $('.searchInput').val();
    		if(searchVal != undefined && $.trim(searchVal).length > 0){
    			var params = $("#f4TableDiv").attr('defaultParams');
            	try {
            		params = JSON.parse(params);
    			} catch (e) {
    				params = {};
    			}
    			params.customSearch = searchVal;
    			var buildUrl = $("#f4TableDiv").attr('defaultUrl')+"/" + encodeURI(JSON.stringify(params));
    			$("#f4TableDiv").data('customSearchVal',searchVal);
                $.getJSON(buildUrl,function(data){
                    refreshTableData(data);
                });
    		}
    	});
    	
        var handle = function(tr){
        	var f4id = $('#f4TableDiv').attr('f4id');
        	var row = {};
        	$($('#f4TableDiv').data('tableHead')).each(function(index,obj){
            	row[obj.key] = tr.find('td:eq(' + index + ')').text();
        	});
            $($('#' + f4id).next()[0]).f4().setValue(row);
            $('#f4Modal').modal('hide');
        };
    	var refreshTableData = function(data){
    		var thead = $('<thead/>');
            if(data && data.heads){
            	var tr = $('<tr/>');
            	$(data.heads).each(function(index,obj){
            		var tha = $('<th/>').attr('col-key',obj.key).text(obj.text);
            		if(!obj.isShow){
            			tha.css('display','none');
            		}
            		tr.append(tha);
            	});
            	thead.append(tr);
            }
            $('#f4TableDiv').data('tableHead',data.heads);
            var tbody = $('<tbody/>');
            var columnIsShow = function(key){
            	var s ;
            	$(data.heads).each(function(index,obj){
            		if(obj.key == key){
            			s = obj.isShow;
            			return false;
            		}
            	});
            	return s || false;
            }
            if(data && data.rows){
            	$(data.rows).each(function(index,obj){
            		var tr = $('<tr/>');
            		for(var r in obj){
            			var td = $('<td/>').text(obj[r]);
            			if(!columnIsShow(r)){
            				td.css('display','none');
            			}
            			tr.append(td);
            		}
            		tbody.append(tr);
            	});
            }
            
            var f4Table = $("<table class='table datatable'></table>");
            $("#f4TableDiv").empty();
            var shtml = $(searchHtml);
            shtml.find('.searchInput').val($("#f4TableDiv").data('customSearchVal'));
            $("#f4TableDiv").append(shtml).append(f4Table.append(thead).append(tbody));
            f4Table.datatable({sortable: true});
            refreshPagination(data.pager);
            $("#f4TableDiv .searchInput").focus();

    	}
    	

        $('#f4TableDiv').delegate(".datatable>.datatable-rows table tr","click",function(){
        	$(this).parent().children().removeClass('active');
            $(this).removeClass('active').addClass('active');
        });
        
        $('#f4TableDiv').delegate(".datatable>.datatable-rows table tr","dblclick",function(){
            handle($(this));
        });
    	
        $(html.children(".input-group-addon")[0]).click(function(){
            var f4Cont = $(this).closest(".f4Contain");
            if(f4Cont.attr("isEditable") == "false"){
                return;
            }
            var f4id = $(this).attr("id");
            var url = $(this).attr("url")||($("body").attr("ctxPath") + "/f4/");
            var table = $(this).attr("table");
            if(!table) throw new Error('f4 的table参数必须指定');
            var urlParams = $(this).attr("urlParams");
            $('#f4Modal').modal();
            var buildUrl = url+table+"/" + encodeURI(urlParams||"{}");
            $.getJSON(buildUrl,function(data){
                $("#f4TableDiv").attr('f4id',f4id).attr('defaultUrl',url+table).attr('defaultParams',urlParams);
                refreshTableData(data);
            })
            return false;
        });
        $('#f4OkButton').on('click',function(){
        	var tr = $("#f4TableDiv .datatable>.datatable-rows table tr.active");
        	if(tr.length > 0){
        		handle(tr);
        	}else{
        		alert("请先选中一行数据。");
        		return;
        	}
        	
        });
        $(this).replaceWith(html);
        return html;
    }

    $(".f4").each(function(){
        $(this).f4();
    });

    $(document).ready(function(){
        $('#f4Modal').on('hidden.bs.modal', function () {
            $("#f4Table").remove();
        })
    });

    $(document).keydown(function(event){
        if(event.keyCode == 46){
            var f4Contain = $(event.target).parent(".f4Contain");
            if(f4Contain.length > 0){
                var f4 = f4Contain.children(".f4-inited");
                $("#" + f4.attr("id")).f4().setValue(null);
            }
        }
    });

})(jQuery);


